package gw.com.android.presenter;

import android.text.TextUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import gw.com.android.app.GTConfig;
import gw.com.android.model.ConfigType;
import gw.com.android.model.ConfigUtil;
import gw.com.android.presenter.http.Https;
import gw.com.android.ui.quote2.QuoteChartConfig;
import okhttp3.Request;
import okhttp3.Response;
import www.com.library.app.Logger;
import www.com.library.util.AESCrypto;

/**
 * 4月-HX-APP交易奖励金活动（活动编号= HX20180416）
 *
 * @author jett
 * @since 2018-03-27.
 */
public class RewardPresenter {

    private final String TAG = "RewardPresenter";

    private static final RewardPresenter instance;

    static {
        instance = new RewardPresenter();
    }

    public static RewardPresenter getInstance() {
        return instance;
    }

    private static final int NONE = 0;
    public static final int OPEN = 1;
    public static final int CLOSE = 2;

    private final String PREF_OPEN_REWARD_COUNT = "pref_open_reward_count";
    private final String PREF_CLOSE_REWARD_COUNT = "pref_close_reward_count";

    private final List<String> products = new ArrayList<>();

    private float minOpenLots; // 最小开仓手数
    private int totalOpenNum;   // 总共可开仓次数
    private int usedOpenNum;    // 成功领取的开仓次数
    private int showedOpenNum;  // 本地记录，开仓奖金已经弹出的次数
    private int totalCloseNum;  // 总共可平仓次数
    private int usedCloseNum;   // 成功领取的平仓奖励次数
    private int showedCloseNum;  // 本地记录，平仓奖金已经弹出的次数

    private int dispatch = NONE;
    private String orderNo;
    private String tradeTime;

    private RewardPresenter() {
        products.add(String.valueOf(QuoteChartConfig.LONDON_GOLD));//伦敦金
        products.add(String.valueOf(QuoteChartConfig.LONDON_SILVER));//伦敦银
    }

    public boolean validateProduct(String productCode) {
        return products.contains(productCode);
    }

    public void onConfig(OnConfigListener listener, int type) {
        Logger.i(TAG, "onConfig type = " + type);
        minOpenLots = 0;
        totalOpenNum = 0;
        usedOpenNum = 0;
        showedOpenNum = 0;
        totalCloseNum = 0;
        usedCloseNum = 0;
        showedCloseNum = 0;
        requestConfig(listener, type);
    }

    public void addShowed(int type) {
        if (type == OPEN) {
            addRewardCount(PREF_OPEN_REWARD_COUNT);
        } else if (type == CLOSE) {
            addRewardCount(PREF_CLOSE_REWARD_COUNT);
        }
    }

    public void getOpenAward(String orderNo, String tradeTime, OnGetRewardListener listener) {
        Logger.i(TAG, "getOpenAward");
        if (dispatch != NONE) {
            return;
        }
        dispatch = OPEN;
        this.orderNo = orderNo;
        this.tradeTime = tradeTime;
        lotteryDraw(listener);
    }

    public void getCloseAward(String orderNo, String tradeTime, OnGetRewardListener listener) {
        Logger.i(TAG, "getCloseAward");
        if (dispatch != NONE) {
            return;
        }
        dispatch = CLOSE;
        this.orderNo = orderNo;
        this.tradeTime = tradeTime;
        lotteryDraw(listener);
    }

    private void requestConfig(final OnConfigListener listener, final int type) {
        JSONObject urlJson = ConfigUtil.instance().getHtmlUrlObject();
        String url = null;
        String activityNo = null;
        if (urlJson != null) {
            JSONObject configJson = urlJson.optJSONObject("rewardConfig");
            if (configJson != null) {
                url = configJson.optString(ConfigType.HTML_DIR_TAG);
                JSONArray params = configJson.optJSONArray(ConfigType.HTML_PARAM_TAG);
                if (params != null && params.length() > 0) {
                    activityNo = params.optString(0);
                }
            }
        }
        if (TextUtils.isEmpty(url) || TextUtils.isEmpty(activityNo)) {
            if (listener != null) {
                listener.onConfig(false, 0, 0, 0);
            }
            return;
        }
        final String mActivityNo = activityNo;
        new Https(url).addParam("activityPeriods", activityNo)
                .addParam("companyId", ConfigUtil.instance().mConfigObject.optString(ConfigType.CHAT_COMPANY_ID_TAG))
                .addParam("key", AESCrypto.encrypt(GTConfig.instance().mCurName))
                .get(new Https.ResponseCallback<String>() {
                    @Override
                    public void onSuccess(Request request, Response response, String result, int code) {
                        Logger.i(TAG, "requestConfig success");
                        onConfigResponse(result, listener, mActivityNo, type);
                    }

                    @Override
                    public void onFailure(Request request, IOException e) {
                        Logger.e(TAG, e);
                        if (listener != null) {
                            listener.onConfig(false, 0, 0, 0);
                        }
                    }
                });
    }

    private void onConfigResponse(String result, OnConfigListener listener, String activityNo, int type) {
        if (!TextUtils.isEmpty(result)) {
            try {
                JSONObject jsonObject = new JSONObject(result);
                boolean hasConfig = jsonObject.optBoolean("ok");
                Logger.i(TAG, "onConfigResponse hasConfig = " + hasConfig);
                if (hasConfig) {
                    JSONObject dataJson = jsonObject.optJSONObject("data");
                    if (dataJson != null) {
                        JSONObject activityJson = dataJson.optJSONObject(activityNo);
                        if (activityJson != null) {
                            minOpenLots = (float) activityJson.optDouble("openMinLot");
                            totalOpenNum = activityJson.optInt("openAwardNumLimit");
                            totalCloseNum = activityJson.optInt("closeAwardNumLimit");
                        } else {
                            minOpenLots = (float) dataJson.optDouble("openMinLot");
                            totalOpenNum = dataJson.optInt("openAwardNumLimit");
                            totalCloseNum = dataJson.optInt("closeAwardNumLimit");
                        }
                        // 开仓配置
                        usedOpenNum = dataJson.optInt("openUsedNum");
                        showedOpenNum = getRewardCount(PREF_OPEN_REWARD_COUNT);
                        // 平仓配置
                        usedCloseNum = dataJson.optInt("closeUsedNum");
                        showedCloseNum = getRewardCount(PREF_CLOSE_REWARD_COUNT);
                    }
                    Logger.i(TAG, "onConfigResponse totalOpenNum = " + totalOpenNum + " usedOpenNum = " + usedOpenNum + " showedOpenNum = " + showedOpenNum);
                    Logger.i(TAG, "onConfigResponse totalCloseNum = " + totalCloseNum + " usedCloseNum = " + usedCloseNum + " showedCloseNum = " + showedCloseNum);
                    if (listener != null) {
                        int remainOpenNum = totalOpenNum - Math.max(usedOpenNum, showedOpenNum);
                        int remainCloseNum = totalCloseNum - Math.max(usedCloseNum, showedCloseNum);
                        listener.onConfig(true, remainOpenNum, remainCloseNum, minOpenLots);
                    }
                    return;
                }
            } catch (JSONException ignore) {
            }
        }
        Logger.i(TAG, "onConfigResponse parse failed");
        if (listener != null) {
            listener.onConfig(false, 0, 0, 0);
        }
    }

    private int getRewardCount(String key) {
        String value = GTConfig.instance().getStringValue(GTConfig.instance().mCurName + key);
        if (!TextUtils.isEmpty(value)) {
            String[] split = value.split("::");
            if (split.length >= 2) {
                String today = new SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(new Date());
                if (today.equals(split[0])) {
                    try {
                        return Integer.parseInt(split[1]);
                    } catch (NumberFormatException ignore) {
                    }
                }
            }
        }
        return 0;
    }

    private void addRewardCount(String key) {
        int count = getRewardCount(key) + 1;
        String today = new SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(new Date());
        String value = today + "::" + count;
        GTConfig.instance().setStringValue(GTConfig.instance().mCurName + key, value);
    }

    private void clear() {
        dispatch = NONE;
        orderNo = null;
        tradeTime = null;
    }

    private void lotteryDraw(final OnGetRewardListener listener) {
        final int type = dispatch;

        JSONObject urlJson = ConfigUtil.instance().getHtmlUrlObject();
        String url = null;
        String activityNo = null;
        if (urlJson != null) {
            JSONObject drawJson = urlJson.optJSONObject("rewardDraw");
            if (drawJson != null) {
                url = drawJson.optString(ConfigType.HTML_DIR_TAG);
                JSONArray params = drawJson.optJSONArray(ConfigType.HTML_PARAM_TAG);
                if (params != null && params.length() > 0) {
                    activityNo = params.optString(0);
                }
            }
        }
        if (TextUtils.isEmpty(url) || TextUtils.isEmpty(activityNo)) {
            if (listener != null) {
                listener.onFailure(null);
            }
            return;
        }
        new Https(url).addParam("activityPeriods", activityNo)
                .addParam("orderNo", orderNo)
                .addParam("reportType", type == OPEN ? "OPEN" : "CLOSE") //  OPEN:开仓， CLOSE：平仓
                //.addParam("tradeTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date()))
                .addParam("tradeTime", tradeTime)
                .addParam("companyId", ConfigUtil.instance().mConfigObject.optString(ConfigType.CHAT_COMPANY_ID_TAG))
                .addParam("key", AESCrypto.encrypt(GTConfig.instance().mCurName))
                .get(new Https.ResponseCallback<String>() {
                    @Override
                    public void onSuccess(Request request, Response response, String result, int code) {
                        Logger.i(TAG, "lotteryDraw success");
                        clear();
                        onlotteryDraw(result, listener, type);
                    }

                    @Override
                    public void onFailure(Request request, IOException e) {
                        Logger.e(TAG, e);
                        clear();
                        if (listener != null) {
                            listener.onFailure(e);
                        }
                    }
                });
    }

    private void onlotteryDraw(String result, OnGetRewardListener listener, int type) {
        Exception exception = null;
        if (!TextUtils.isEmpty(result)) {
            try {
                JSONObject jsonObject = new JSONObject(result);
                boolean ok = jsonObject.optBoolean("ok", false);
                Logger.i(TAG, "onlotteryDraw isOk = " + ok);
                if (ok) {
                    JSONObject dataJson = jsonObject.optJSONObject("data");
                    if (dataJson != null) {
                        String money = dataJson.optString("giftName");
                        if (listener != null) {
                            if (type == OPEN) {
                                usedOpenNum++;
                            } else if (type == CLOSE) {
                                usedCloseNum++;
                            }
                            listener.onSuccess(money, totalOpenNum - usedOpenNum, totalCloseNum - usedCloseNum);
                        }
                        return;
                    }
                }
            } catch (JSONException e) {
                exception = e;
            }
        }
        Logger.i(TAG, "onlotteryDraw .. failed...");
        if (listener != null) {
            listener.onFailure(exception);
        }
    }

    public int getTotalOpenNum() {
        return totalOpenNum;
    }

    public int getTotalCloseNum() {
        return totalCloseNum;
    }

    public float getMinOpenLots() {
        return minOpenLots;
    }

    public interface OnConfigListener {

        void onConfig(boolean hasConfig, int remainOpenNum, int remainCloseNum, float minLots);

    }

    public interface OnGetRewardListener {

        void onSuccess(String money, int remainOpenNum, int remainCloseNum);

        void onFailure(Exception e);

    }

}
